package com.ljm.shiro.core;

import com.ljm.common.util.StringUtil;
import com.ljm.shiro.enums.UserStatusEnums;
import com.ljm.shiro.util.UserUtil;
import com.ljm.sys.org.api.SysOrgUserApi;
import com.ljm.sys.org.dto.SysOrgUserDto;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;

import javax.annotation.Resource;

/**
 * 版权：    Copyright by ljm
 * 描述：
 * 修改人：  HuamingChen
 * 修改时间：2018/12/11
 * 跟踪单号：
 * 修改单号：
 * 修改内容：
 */
public class ShiroRealm extends AuthorizingRealm {
    /**
     * 日志
     */
    private static final Logger LOG = LoggerFactory.getLogger(ShiroRealm.class);

    /**
     * 用户接口
     */
    @Resource
    @Lazy//防止该实现类没有事务
    private SysOrgUserApi sysUserApi;
    /**
     * 鉴权
     *
     * @param principals 权限
     * @return 权限信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        LOG.debug("###################开始鉴权######################");
        String loginName = (String) principals.getPrimaryPrincipal();

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        // 获取登录用户
        SysOrgUserDto userInfo = UserUtil.getUser(loginName);

        // 查询角色信息
        if (!StringUtil.isEmpty(userInfo.getRoles())) {
            authorizationInfo.setRoles(userInfo.getRoles());
            // 查询权限
            if (!StringUtil.isEmpty(userInfo.getPermissions())) {
                authorizationInfo.setStringPermissions(userInfo.getPermissions());
            }
        }
        //缓存用户权限信息
        return authorizationInfo;
    }

    /**
     * 登录认证
     *
     * @param token 用户登录token
     * @return 权限信息
     * @throws AuthenticationException 登录异常
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
        LOG.debug("###################登录校验######################");
        // 解密获得username，用于和数据库进行对比
        String loginName = (String) token.getPrincipal();
        if (StringUtil.isEmpty(loginName.trim())) {
            throw new UnknownAccountException();// 没找到帐号
        }
        // 根据登录用户信息
        SysOrgUserDto userInfo = sysUserApi.getUserByUserName(loginName);
        if (StringUtil.isEmpty(userInfo)) {
            throw new UnknownAccountException("用户名错误，请重新输入");// 没找到帐号
        }
        // 判断用户状态
        if (UserStatusEnums.FROZEN.getCode()==userInfo.getStatus()) {
            throw new LockedAccountException("该用户已经被冻结，请联系管理员");
        } else if (UserStatusEnums.CANCEL.getCode()==userInfo.getStatus()) {
            throw new LockedAccountException("该用户注销，请联系管理员");
        }
        // 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配
        return new SimpleAuthenticationInfo(
                userInfo.getLoginName(), // 登录名
                userInfo.getLoginPwd(), // 密码
                ByteSource.Util.bytes(userInfo.getSalt()), this.getName() // realm name
        );
    }
}
